#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <mutex>
#include <atomic>
#include <thread>

#include "common/net_utils.h"
#include "net_tools.h"

using namespace std;

#define SERVER_HOST "127.0.0.1"
#define SERVER_PORT 6666

//#define CREATE_TASK CoApi::create

atomic<int>  g_ends(0);
atomic<long> g_counter(0);

int main(int argc, char** argv)
{
	NetTools::ignore_sig_pipe();

//    LogDefaulter::set_log_level(LOG_LEVEL_DEBUG);
//    LogDefaulter::set_logger([](const string& message) {
//        printf("socket_test|%s\n", message.c_str());         
//    });

    CoClientCb cb;
    cb.connect_cb = [](int fd, bool is_ok) {
		PRINTF("##### cb #####|client connect %s, fd:%d", is_ok ? "succeed" : "fail", fd);
	};
    cb.send_cb = [](int fd, const string& buffer, bool is_ok) {
       // PRINTF("##### cb #####|client send %s, fd:%d, buffer:%s", is_ok ? "succeed" : "fail", fd, buffer.c_str());
	    g_counter++;
    };
    cb.recv_cb = [](int fd, const string& buffer, bool is_ok) {
       // PRINTF("##### cb #####|client recv %s, fd:%d, buffer:%s", is_ok ? "succeed" : "fail", fd, buffer.c_str());
    };
    cb.close_cb = [](int fd) {
        PRINTF("##### cb #####|server close, fd:%d", fd);
    }; 

    int client_count = 1;
    if (argc == 2) {
        client_count = atoi(argv[1]);
    }

    atomic<int> coroutines(0);

    string server_host = SERVER_HOST;
    int    server_port = SERVER_PORT;

    if (argc >= 2) {
        client_count = atoi(argv[1]); 
    } 
    if (argc >= 3) {
        server_host = argv[2]; 
    }
    if (argc >= 4) {
        server_port = atoi(argv[3]); 
    }

    PRINTF(
        "host:%s, port:%d, client_count:%d", 
        server_host.c_str(), 
        server_port, 
        client_count
    );

    for (int i = 0; i < client_count; i++) {
       // CREATE_TASK([&coroutines, server_host, server_port, cb] {
        NetTools::create_task([&coroutines, server_host, server_port, cb] {
            coroutines++; 
            PRINTF("########## coroutine running, tag:send_co");
            NetTools::normal_sender(server_host, server_port, -1, cb);
            PRINTF("########## coroutine end, tag:send_co");
            g_ends++;
        }); 
    }

	long last_counter = 0;
	while (g_ends.load() != client_count) {
		usleep(1000 * 1000);
		long now_counter = g_counter.load();
        PRINTF("++++++++++ qps:%ld, coroutine_count:%d", now_counter - last_counter, coroutines.load());
		last_counter = now_counter;
	}

    PRINTF("main end");

    return 0;
}

